package com.informatics.polymer.client.propertysearch;

import java.util.ArrayList;

import org.restlet.gwt.Callback;
import org.restlet.gwt.Client;
import org.restlet.gwt.data.Form;
import org.restlet.gwt.data.Protocol;
import org.restlet.gwt.data.Request;
import org.restlet.gwt.data.Response;
import org.restlet.gwt.resource.Representation;

import com.google.gwt.user.client.Window;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.DragDataAction;
import com.smartgwt.client.types.ListGridEditEvent;
import com.smartgwt.client.types.ListGridFieldType;
import com.smartgwt.client.types.SelectionAppearance;
import com.smartgwt.client.types.TreeModelType;
import com.smartgwt.client.widgets.Button;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.CellClickEvent;
import com.smartgwt.client.widgets.grid.events.CellClickHandler;
import com.smartgwt.client.widgets.layout.HStack;
import com.smartgwt.client.widgets.tree.Tree;
import com.smartgwt.client.widgets.tree.TreeGrid;
import com.smartgwt.client.widgets.tree.TreeNode;

/**
 * Class to display a tree for property selection.
 * 
 * @author ed
 * @version 1.0
 */
public class PropertyTree {
	/**
	 * ArrayList to store selected properties.
	 */
	private ArrayList<String> selectedProperties = new ArrayList<String>();

	/**
	 * Create a PropertyTree object.
	 */
	public PropertyTree() {
	}

	/**
	 * 
	 * @return ArrayList<String> containing all properties to search for.
	 */
	public ArrayList<String> getSelectedProperties() {
		return selectedProperties;
	}

	/**
	 * Create property tree.
	 * 
	 * @return Tree containing all descriptor properties from the CDK.
	 */
	public HStack createPropertyTree() {
		final Tree grid1Tree = new Tree();
		grid1Tree.setModelType(TreeModelType.CHILDREN);
		grid1Tree.setNameProperty("Name");
		final PartsTreeNode property = new PartsTreeNode("Property");
		property.setAttribute("Name", "Root");
		grid1Tree.setRoot(property);
		PartsTreeNode alogP = new PartsTreeNode("ALOGP");
		alogP.setAttribute("Name", "ALOGP");
		PartsTreeNode aLogP2 = new PartsTreeNode("ALogP2");
		aLogP2.setAttribute("Name", "ALogP2");
		PartsTreeNode amr = new PartsTreeNode("AMR");
		amr.setAttribute("Name", "AMR");
		PartsTreeNode aPol = new PartsTreeNode("APol");
		aPol.setAttribute("Name", "APol");
		PartsTreeNode aromaticAtomCount = new PartsTreeNode("AromaticAtomCount");
		aromaticAtomCount.setAttribute("Name", "AromaticAtomCount");
		PartsTreeNode aromaticBondCount = new PartsTreeNode("AromaticBondCount");
		aromaticBondCount.setAttribute("Name", "AromaticBondCount");
		PartsTreeNode atomCount = new PartsTreeNode("AtomCount");
		atomCount.setAttribute("Name", "AtomCount");
		PartsTreeNode bondCount = new PartsTreeNode("BondCount");
		bondCount.setAttribute("Name", "BondCount");
		PartsTreeNode fragmentComplexity = new PartsTreeNode(
				"FragmentComplexity");
		fragmentComplexity.setAttribute("Name", "FragmentComplexity");
		PartsTreeNode hbaCount = new PartsTreeNode("HBACount");
		hbaCount.setAttribute("Name", "HBACount");
		PartsTreeNode hbdCount = new PartsTreeNode("HBDCount");
		hbdCount.setAttribute("Name", "HBDCount");
		PartsTreeNode kappa1 = new PartsTreeNode("Kappa1");
		kappa1.setAttribute("Name", "Kappa1");
		PartsTreeNode kappa2 = new PartsTreeNode("Kappa2");
		kappa2.setAttribute("Name", "Kappa2");
		PartsTreeNode kappa3 = new PartsTreeNode("Kappa3");
		kappa3.setAttribute("Name", "Kappa3");
		PartsTreeNode ruleOf5 = new PartsTreeNode("RuleOf5");
		ruleOf5.setAttribute("Name", "ruleOf5");
		PartsTreeNode tpsa = new PartsTreeNode("TPSA");
		tpsa.setAttribute("name", "TPSA");
		grid1Tree.add(alogP, property);
		grid1Tree.add(aLogP2, property);
		grid1Tree.add(amr, property);
		grid1Tree.add(aPol, property);
		grid1Tree.add(aromaticAtomCount, property);
		grid1Tree.add(aromaticBondCount, property);
		grid1Tree.add(atomCount, property);
		grid1Tree.add(bondCount, property);
		grid1Tree.add(fragmentComplexity, property);
		grid1Tree.add(hbaCount, property);
		grid1Tree.add(hbdCount, property);
		grid1Tree.add(kappa1, property);
		grid1Tree.add(kappa2, property);
		grid1Tree.add(kappa3, property);
		grid1Tree.add(ruleOf5, property);
		grid1Tree.add(tpsa, property);
		final PartsTreeGrid grid1 = new PartsTreeGrid();
		grid1.setDragDataAction(DragDataAction.MOVE);
		grid1.setData(grid1Tree);
		grid1.getData().openAll();
		ListGrid propertyGridToEdit;
		final HStack grids = new HStack(10);
		grid1.addCellClickHandler(new CellClickHandler() {
			@Override
			public void onCellClick(CellClickEvent event) {
				Window.alert(event.getRecord().getAttribute("Name"));
			}
		});
		Button displaySelectedProperties = new Button("Set Property Ranges");
		displaySelectedProperties.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				Window.alert(Integer.toString(grid1.getSelection().length));
				ListGridRecord[] selectedResults = grid1.getSelection();
				for (int i = 0; i < selectedResults.length; i++) {
					Window.alert(selectedResults[i].getAttribute("Name"));
					selectedProperties.add(selectedResults[i]
							.getAttribute("Name"));
				}
				// Add listgrid.
				final ListGrid propertyGridSelect = propertySelectedGrid(selectedProperties);
				grids.addMember(propertyGridSelect);
				// Add additional button to submit search to restlet.
				Button submitPropertySearch = new Button("Submit");
				submitPropertySearch.setSize("200", "30");
				submitPropertySearch.addClickHandler(new ClickHandler() {
					@Override
					public void onClick(ClickEvent event) {
						// Extracts edited cell values.
						String data4Restlet = "";
						for (int i = 0; i < selectedProperties.size(); i++) {
							String property = "";
							for (int j = 0; j < 3; j++) {
								if (j < 2) {
									String dataRow = propertyGridSelect
											.getEditedCell(i, j).toString()
											+ ",";
									data4Restlet = data4Restlet + dataRow;
								} else if (j == 2) {
									String dataRow = propertyGridSelect
											.getEditedCell(i, j).toString()
											+ ";";
									data4Restlet = data4Restlet + dataRow;
								}
							}
						}
						Window.alert(data4Restlet);
						// Restlet to invoke property search and display grid.
						final Client client = new Client(Protocol.HTTP);
						Form form = new Form();
						form.add("propertyInfo",data4Restlet);
						Representation rep = form.getWebRepresentation();
						client.post("http://localhost:8080/svc/propertySearch", rep, new Callback() {
							@Override
							public void onEvent(Request request,
									Response response) {
								//Window alert for text response.
							//	String resultantText = response.getEntity().getText();
							//	com.google.gwt.user.client.Window.alert(resultantText);
							}
						});

					}

				});
				grids.addMember(submitPropertySearch);
			}
		});
		displaySelectedProperties.setSize("200", "30");
		grids.setHeight(160);
		grids.addMember(grid1);
		grids.addMember(displaySelectedProperties);
		return grids;
	}

	public static class PartsTreeGrid extends TreeGrid {
		public PartsTreeGrid() {
			setWidth(200);
			setHeight(200);
			setShowEdges(true);
			setBorder("0px");
			setBodyStyleName("normal");
			setAlternateRecordStyles(true);
			setShowHeader(false);
			setLeaveScrollbarGap(false);
			setManyItemsImage("cubes_all.png");
			setAppImgDir("pieces/16/");
			setCanReorderRecords(true);
			setCanAcceptDroppedRecords(false);
			setCanDragRecordsOut(true);
			setAddDropValues(true);
			setSelectionAppearance(SelectionAppearance.CHECKBOX);
		}
	}

	public static class PartsTreeNode extends TreeNode {
		public PartsTreeNode(String name, String icon) {
			this(name, icon, new PartsTreeNode[] {});
		}

		public PartsTreeNode(String name, PartsTreeNode... children) {
			this(name, null, children);
		}

		public PartsTreeNode(String name, String icon,
				PartsTreeNode... children) {
			setAttribute("Name", name);
			setAttribute("children", children);
			if (icon != null)
				setAttribute("icon", icon);

		}
	}

	private ListGrid propertySelectedGrid(ArrayList<String> properties) {
		ListGrid propertyGrid = new ListGrid();
		propertyGrid.setWidth(350);
		propertyGrid.setHeight(200);
		propertyGrid.setAlternateRecordStyles(true);
		propertyGrid.setShowAllRecords(true);
		propertyGrid.setCellHeight(22);
		ListGridField propertyNameField = new ListGridField("Property",
				"Property");
		ListGridField maxField = new ListGridField("Maximum", "Maximum");
		ListGridField minField = new ListGridField("Minimum", "Minimum");
		propertyNameField.setAlign(Alignment.CENTER);
		maxField.setAlign(Alignment.CENTER);
		minField.setAlign(Alignment.CENTER);
		maxField.setType(ListGridFieldType.FLOAT);
		minField.setType(ListGridFieldType.FLOAT);
		propertyGrid.setFields(propertyNameField, maxField, minField);
		propertyGrid.setCanEdit(true);
		propertyGrid.setEditEvent(ListGridEditEvent.CLICK);
		propertyGrid.setEditByCell(true);
		// Set data
		PropertySearchDataRecord[] dataRecords = new PropertySearchDataRecord[properties
				.size()];
		for (int i = 0; i < properties.size(); i++) {
			PropertySearchDataRecord propertySearchDataRecord = new PropertySearchDataRecord(
					properties.get(i), 0.0, 0.0);
			propertySearchDataRecord.setAttribute("Property",
					propertySearchDataRecord.getProperty());
			dataRecords[i] = propertySearchDataRecord;
		}
		propertyGrid.setData(dataRecords);
		return propertyGrid;
	}
}
